﻿using AutoMapper;
using Library.API.Entities;
using Library.API.Models;
using Library.API.Repositories.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Library.API.Controllers
{
    [Route("api/users")]
    [ApiController]
    [Authorize]
    public class UserController : Controller
    {
        private IMapper Mapper;

        private IRepositoryWrapper RepositoryWrapper;

        public UserController(IRepositoryWrapper repositoryWrapper, IMapper mapper)
        {
            this.RepositoryWrapper = repositoryWrapper;
            this.Mapper = mapper;
        }

        [Authorize(Roles = "Administrator")]
        public async Task<ActionResult<List<UserDto>>> GetUsersAsync()
        {
            var users = await Task.FromResult<IEnumerable<User>>(this.RepositoryWrapper.UserManager.Users);
            return this.Mapper.Map<List<UserDto>>(users);
        }

        [HttpGet("{userId}", Name = nameof(GetUserAsync))]
        public async Task<ActionResult<UserDto>> GetUserAsync(string userId)
        {
            var user = await this.RepositoryWrapper.UserManager.FindByIdAsync(userId);
            if (user == null)
            {
                return NotFound();
            }

            var userDto = this.Mapper.Map<UserDto>(user);
            return userDto;
        }

        [HttpPost("register", Name = nameof(AddUserAsync))]
        [AllowAnonymous]
        public async Task<ActionResult> AddUserAsync(RegisterUser registerUser)
        {
            var user = this.Mapper.Map<User>(registerUser);
            IdentityResult result = await this.RepositoryWrapper.UserManager.CreateAsync(user, registerUser.Password);
            if (result.Succeeded)
            {
                return Ok();
            }
            else
            {
                ModelState.AddModelError("Error", result.Errors.FirstOrDefault()?.Description);
                return BadRequest(ModelState);
            }
        }

        [HttpPost("grant")]
        [Authorize(Roles = "Administrator")]
        public async Task<ActionResult> AddUserToRoleAsync(GrantDto grantDto)
        {
            var user = await this.RepositoryWrapper.UserManager.FindByIdAsync(grantDto.UserId);
            if (user == null)
            {
                return NotFound();
            }

            var result = await this.AddUserToRoleAsync(user, grantDto.RoleName);
            if (!result.Value.Succeeded)
            {
                throw new Exception(result.Value.Errors.FirstOrDefault().Description);
            }

            return NoContent();
        }

        private async Task<ActionResult<IdentityResult>> AddUserToRoleAsync(User user, string roleName)
        {
            if (user == null)
            {
                var error = new IdentityError()
                {
                    Code = "Error_001",
                    Description = "用户不存在"
                };
                return IdentityResult.Failed(error);
            }

            if (string.IsNullOrWhiteSpace(roleName))
            {
                var error = new IdentityError()
                {
                    Code = "Error_002",
                    Description = "角色名称为空"
                };
                return IdentityResult.Failed(error);
            }

            bool isRoleExist = await this.RepositoryWrapper.RoleManager.RoleExistsAsync(roleName);
            if (!isRoleExist)
            {
                await this.RepositoryWrapper.RoleManager.CreateAsync(new Role { Name = roleName });
            }
            else
            {
                if (await this.RepositoryWrapper.UserManager.IsInRoleAsync(user, roleName))
                {
                    return IdentityResult.Success;
                }
            }

            return await this.RepositoryWrapper.UserManager.AddToRoleAsync(user, roleName);
        }
    }
}
